/** \file    Statistics.cpp
  * \brief   Statistical functions.
  * \date    2001
  * \author  Fedor Chelnokov
  * \version $Header: /home/cscom1r4/cvsroot/cs/segm/src/Statistics.cpp,v 1.1 2004/05/20 09:11:46 cscom1r4 Exp $
  */

#include "segm/Segmentation.h"
#include "segm/PixelIterator.h"
#include "imglib/image.h"
#include <algorithm>
//#include <iostream>

static inline void initMeanDisp( Segment &g ) {
	g.meanColor = float_color();
	g.colorDispersion = 0;
}

static inline void normMean( Segment &g ) {
	g.meanColor *= 1.0 / g.pixelCount;
//	std::clog << "mean=(" << g.meanColor.r << ',' << g.meanColor.g << ',' << g.meanColor.b << ")\n";
}

static inline void normDisp( Segment &g ) {
	if( g.pixelCount > 1 ) {
		g.colorDispersion *= (1.0 / (g.pixelCount-1));
	} else {
		g.colorDispersion = 0;
	}
//	std::clog << "dispersion=" << g.colorDispersion << std::endl;
}

class upThrsInsteadDisp_g
{
public:
	upThrsInsteadDisp_g(float factorSqSigma) : _factorSqSigma(factorSqSigma) {}
	void operator ()(Segment &g) {
		g.colorDispersion *= _factorSqSigma;
		if (g.colorDispersion == 0.0)
			g.colorDispersion = 1e-5;
	}

private:
	float _factorSqSigma;
};

void Segmentation::colorStatistics(
	bool upThrsInsteadDisp, ///< replaces dispersion in all segments on max(epsilon,dispersion*param.factorSqSigma)
	float factorSqSigma)
{
	if (m_colorStatisticsFound && m_upThrsInsteadDisp == upThrsInsteadDisp) 
		return;
	assert(m_sourceImage);

	std::for_each(segmentsBegin(), segmentsEnd(), initMeanDisp);

	float_image::const_iterator fIt = m_sourceImage->begin();
	PixelIterator i(*this, true);
	for( ; fIt != m_sourceImage->end(); ++i, ++fIt ) {
		if (!i) 
			continue;
		i->meanColor += *fIt;
	}
	std::for_each(segmentsBegin(), segmentsEnd(), normMean);

	fIt = m_sourceImage->begin();
	i = PixelIterator(*this, true);
	for( ; fIt != m_sourceImage->end(); ++i, ++fIt ) {
		if (!i) 
			continue;
		i->colorDispersion += square(small_float_color(*fIt) - i->meanColor);
	}

	std::for_each(segmentsBegin(), segmentsEnd(), normDisp);

	if (upThrsInsteadDisp)
		std::for_each(segmentsBegin(), segmentsEnd(), upThrsInsteadDisp_g(factorSqSigma));

	m_colorStatisticsFound = true;
	m_upThrsInsteadDisp = upThrsInsteadDisp;
}
